
import { delay } from "./AIUtils";

/**
 * 所有类型的对象和属性的AI描述
 */

export async function createSkyPanoramaMtl(filename:string,overWrite?: boolean){
    //let fullname = path.join(Editor.assetDb.toFullPath(''), filename)
    let newAsset = await Editor.assetDb.createFileFromTemplate(filename, 'MaterialSkyPanoramic.json', {type: "SkyPanoramic"},overWrite);
    await delay(1000)
    return newAsset;
}

export async function createPBRMtl(filename:string,overWrite?: boolean){
    let newAsset = await Editor.assetDb.createFileFromTemplate(filename, 'MaterialPBR.json', {type: "PBR"},overWrite);
    //不加延时会出现设置了材质然后被冲掉的效果。
    await delay(1000)
    //let p = await Editor.scene.getResourceProps(newAsset.id)
    return newAsset;
}

export async function creatUnlightMtl(filename:string,overWrite?: boolean){
    let newAsset = await Editor.assetDb.createFileFromTemplate(filename, 'MaterialUnlit.json', {type: "Unlit"},overWrite);
    await delay(1000)
    return newAsset;
}


export class ObjectDesc{
    static allData={
"Scene3D":"场景"
    }
}

/**
 * 查找对象的方法
 * 返回datapath
 */
export function getChildByType(data:any,type:string){
    if(!data.children)
        return null;

    for(let i=0,n=data.children.length; i<n; i++){
        let child = data.children[i];
        if(child.type==type || child._$type==type)
            return '_children['+i+']';
    }
    return null;
}

export async function getChildByName(data:any, name:string, recursive=false){
    if(!data.children)
        return null;

        try{
    for( let child of data.children){
        if(child.name==name)
            return child;
        if(recursive){
            try{
                await Editor.scene.getNodeChildren(child);
                let ret = await getChildByName(child,name,recursive) as any;
                if(ret)
                    return ret;
            }catch(e){
                debugger;
            }
        }
    }
}catch(e){
    debugger;
}
    return null;
}

export async function getCompByType(data:any,type:string, onlyPath=true, recursive=false, syncNode=false){
    await Editor.scene.syncNode(data);
    if(!data.components)
        return null;
    for(let m in data.components){
        let comp = data.components[m];
        if(comp.type==type || comp._$type==type){
            if(onlyPath)
                return 'components.'+m;
            else
                return comp;
        }
    }

    if(recursive){
        let retpath = '';
        if(!data.children){
            return null;
        }
        if(onlyPath){
            retpath = 'children';
        }
        await Editor.scene.getNodeChildren(data);
        for(let i=0,n=data.children.length; i<n; i++){
            let child = data.children[i];
            let comp = await getCompByType(child,type,onlyPath,recursive) as any;
            if(comp)
                return comp;
        }
    }
    return null;
}

export async function getNodeHasComp(data:any,type:string){
    if(!data.children)
        return null;

    for(let i=0,n=data.children.length; i<n; i++){
        let child = data.children[i];
        let comp = await getCompByType(child,type,false);
        if(comp)
            return child;
    }
    return null;
}


export class ShortNameGlobal{
    static allData:{[key:string]:{parent?:string,datapath?:string,getType?:Function, args?:string[], result?:any}}={

"3D场景对象":{
    //没有parent则是从window开始
    datapath:"Editor.scene.rootNode.children[0]",
},
"场景对象":{
    parent:"3D场景对象",
    datapath:"",    //这个表示就是parent
},
"2D场景对象":{
    datapath:"Editor.scene.rootNode.children[1]",
},
"天空盒":{
    parent:"场景对象",
    datapath:"props.skyRenderer",
},
"主光源":{
    parent:"场景对象",
    getType:getChildByType,
    args:["DirectionLight"],
}
    }
}

/**
 * 根据描述得到对象
 * @param objdesc
 * @returns
 */
export async function getObjectByDesc(objdesc:string){
    let desc = ShortNameGlobal.allData[objdesc];
    if(!desc){
       return null;
    }
    //如果已经缓存了查找结果了，直接返回
    if(desc.result)
        return desc.result;

    let parent:any = null;
    if(desc.parent){
        parent = await getObjectByDesc(desc.parent);
        if(!parent){
            return null;
        }
    }
    //没有parent就从window开始
    if(!parent) parent = window;
    if(!desc.datapath){
        if(desc.getType && desc.args && desc.args.length>0){
            //从gettype函数中获取datapath
            desc.datapath = await desc.getType(...desc.args);
        }
    }
    //没有datapath则自己就是parent
    if(!desc.datapath){
        return parent;
    }

    //根据datapath查找对象
    let paths = desc.datapath.split('.');
    let obj = parent;
    for(let i=0,n=paths.length; i<n; i++){
        let path = paths[i];
        //处理数组形式
        let index = path.indexOf('[');
        if(index>0){
            let arrname = path.substr(0,index);
            let arrindex = parseInt(path.substr(index+1));
            obj = obj[arrname][arrindex];
        }else{
            obj = obj[path];
        }
        if(!obj)
            return null;
    }
    return obj;
}

export function getObjectByDataPath(obj:any, datapath:string){
    //根据datapath查找对象
    let paths = datapath.split('.');
    for(let i=0,n=paths.length; i<n; i++){
        let path = paths[i];
        //处理数组形式
        let index = path.indexOf('[');
        if(index>0){
            let arrname = path.substr(0,index);
            let arrindex = parseInt(path.substr(index+1));
            obj = obj[arrname][arrindex];
        }else{
            obj = obj[path];
        }
        if(!obj && i<n-1)
            return null;
    }
    return obj;
}

/**
 * 根据datapath设置变量的值
 * 特殊的地方是可以跨对象，即某个属性如果当前是uuid，则先找到uuid对应的资源，继续设置
 */
export async function setPropsByRefDataPath(obj:any, datapath:string, value:any){
    let paths = datapath.split('.');
    let obj2 = obj;
    for(let i=0,n=paths.length-1; i<n; i++){
        let path = paths[i];
        //处理数组形式
        let index = path.indexOf('[');
        if(index>0){
            let arrname = path.substr(0,index);
            let arrindex = parseInt(path.substr(index+1));
            obj2 = obj2[arrname][arrindex];
        }else{
            obj2 = obj2[path];
        }
        if(!obj2)
            return ;
        if(obj2._$uuid){
            //如果是uuid，则找到uuid所指向的资源
            obj2 = await Editor.resourceManager.getResourceProps(obj2._$uuid);
            if(!obj2){
                return ;
            }
        }
    }
    if(obj2){
        let lastPath = paths[paths.length-1];
        let index = lastPath.indexOf('[');
        if(index>0){
            let arrname = lastPath.substr(0,index);
            let arrindex = parseInt(lastPath.substr(index+1));
            obj2[arrname][arrindex] = value;
        }else{
            obj2[lastPath] = value;
        }
    }
}


export class PropDescMgr{
    static allData:any={
        "Sprite3D":{
            "渲染器":{
                getType:getCompByType,
                args:["MeshRenderer"],
            },
            "renderer":{
                parent:"渲染器",
            },
            "材质":{
                parent:"渲染器",
                datapath:"props.sharedMaterials[0]",  //TODO 多个材质的处理
                },
            "贴图":{
                parent:"材质",
                datapath:"shaderHelper.u_AlbedoTexture",
                type:"Image",
                ready:async (obj:any)=>{
                    //TODO 如果有了不要创建。如果是缺省的，要创建
                    //TODO 临时 先写死了，实际应该在材质那里做
                    let datapath = await getCompByType(obj,'MeshRenderer');
                    if(!datapath)return;
                    datapath+='.props.sharedMaterials[0]'
                    //let mtl = await createPBRMtl(obj.id+"_pbr_ai.lmat");
                    let mtl = await creatUnlightMtl(obj.id+"_unlit_ai.lmat");
                    await setPropsByRefDataPath(obj,datapath,{_$uuid:mtl.id,_$type: "Material"});
                    //await setPropsByRefDataPath(obj,datapath,mtl.id);
                    //obj.material = {_$uuid:mtl.id};
                }
            },
            "texture":{
                parent:"贴图",
            }

        },
        "Material":{
            "贴图":{
                //TODO 不同的材质的贴图的路径不一样
                datapath:"shaderHelper.u_AlbedoTexture",
                type:"Image",
            },
            "漫反射图片":{
                parent:"贴图",
            },
            "纹理":{
                parent:"贴图",
            },
            "颜色":{
                datapath:"shaderHelper.u_AlbedoColor",
                type:"Color",   //只接收Color类型的值
            }
        },
        "SkyRenderer":{
            "贴图":{
                datapath:"material.shaderHelper.u_Texture",
                type:"Image.Panorama",
                ready:async (obj:any)=>{
                    //TODO 如果有了不要创建。如果是缺省的，要创建
                    let mtl = await createSkyPanoramaMtl("skypanoramic_ai.lmat");
                    obj.material = {_$uuid:mtl.id};
                }
            },
            "材质":{    //材质就是贴图
                parent:"贴图",
            },
            "图片":{    //图片就是贴图
                parent:"贴图",
            }
        }
    }

    /**
     * 根据描述找到属性相对于obj的路径
     * @param objdesc
     * @param propdesc
     */
    static async getPropDesc(obj:any,propdesc:string, ret:(msg:string)=>void){
        let type = obj._$type || obj.type;
        let propsDesc = PropDescMgr.allData[type];
        if(propsDesc){
            //找到属性对应的datapath和类型
            let desc = propsDesc[propdesc];
            if(!desc){
                ret(`${type}没有[${propdesc}]属性`)
            }else{
                //缺省的parent是当前对象
                let parent = obj;
                //
                let parentPath:string = null;
                if(desc.parent){
                    //先获得parent的datapath
                    let parentinfo = await PropDescMgr.getPropDesc(obj,desc.parent,ret);
                    parentPath = parentinfo?.datapath;
                }
                let mypath = desc.datapath;
                if(desc.getType && desc.args && desc.args.length>0){
                    mypath = await desc.getType(parent, ...desc.args);
                    if(!mypath){
                        console.error('没有找到属性描述')
                        return null;
                    }
                }
                return {datapath:parentPath?(parentPath+'.'+mypath):mypath, type:desc.type, ready:desc.ready};
            }
        }else{
            console.error('没有找到对象类型:'+type);
        }
        return null;
    }
}

export class Tokens{
    static data = {
'sce':'',
'Scene':'',
'3D':'',
'2D':'',
'场景':'',
'对象':'',
'材质':'',
'贴图':'',
'纹理':'',
'图片':'',
'img':'',
'image':'',
'模型':'',
'动画':'',
'片段':'',
'剪辑':'',
'主':'',
'光源':'',
'强度':'',
'亮度':'',
'颜色':'',
'值':'',
'缺省':'',
'默认':'',
'def':'',
'default':'',
'天空盒':'',
    }
}

export class PropValue{
    toType(type:string):any{
    }
}

export class PropValueColor extends PropValue{
    r=1;    g=1;    b=1;    a=1;
    constructor(){
        super();
    }
    toType(type: string): any {
        if(type=='Color'){
            return {
                r:this.r,
                g:this.g,
                b:this.b,
                a:this.a,
                _$type:'Color'
            }
        }
    }
}
